package com.tma.demo;

import java.lang.ref.WeakReference;
import java.util.Random;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.os.AsyncTask;
import android.os.AsyncTask.Status;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class AsynNondeterministicActivity extends Activity implements OnClickListener {

    private static final String TAG = "AsynNondeterministicActivity";
    private TextView mTaskProgressTextView;
    private Button mAsynButton;
    private NondeterministicTask mAsynTask;

    @SuppressWarnings("deprecation")
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_asyn_nondeterministic);

        mTaskProgressTextView = (TextView) findViewById(R.id.tv_task_progress);
        mAsynButton = (Button) findViewById(R.id.btn_do_long_task);
        mAsynButton.setOnClickListener(this);

        mAsynTask = (NondeterministicTask) getLastNonConfigurationInstance();
        if (mAsynTask != null) {
            mAsynTask.attach(this);
            mAsynTask.resumeProgressDialogIfNeeded();
        }
    }

    @Override
    @Deprecated
    public Object onRetainNonConfigurationInstance() {
        return mAsynTask;
    }

    @Override
    protected void onDestroy() {
        if (mAsynTask != null) {
            mAsynTask.hideProgressDialog();
        }
        super.onDestroy();
    }

    public void updateStatus(String status) {
        mTaskProgressTextView.setText(status);
    }

    public void onClick(View v) {
        handleButtonClicked();
    }

    private void handleButtonClicked() {
        if (mAsynTask == null || mAsynTask.getStatus() == Status.FINISHED) {
            mAsynTask = new NondeterministicTask(this);
            mAsynTask.execute();
            return;
        }
        if (mAsynTask.getStatus() != Status.FINISHED) {
            Toast.makeText(this, "The asyn task is not finished yet", Toast.LENGTH_SHORT).show();
        }
    }

    private static class NondeterministicTask extends AsyncTask<Void, Void, Long> implements OnCancelListener {
        private ProgressDialog mProgressDialog;
        private WeakReference<AsynNondeterministicActivity> mActivityRef;

        public NondeterministicTask(AsynNondeterministicActivity activity) {
            attach(activity);
        }

        @Override
        protected void onPreExecute() {
            Log.i(TAG, "starting");
            AsynNondeterministicActivity activity = mActivityRef.get();
            if (activity != null) {
                mProgressDialog = new ProgressDialog(mActivityRef.get());
                mProgressDialog.setTitle("Please wait");
                mProgressDialog.setMessage("Processing...");

                mProgressDialog.setCancelable(true);
                mProgressDialog.setOnCancelListener(this);
                mProgressDialog.show();
            }
        }

        @Override
        protected Long doInBackground(Void... params) {
            // THIS METHOD RUNS ON WORKER THREAD
            // DO NOT UPDATE UI HERE!!!
            long time = System.currentTimeMillis();
            Random r = new Random();
            long n = r.nextInt(50) + 100;
            for (int i = 0; i < n; i++) {
                // we want to cancel the task as quickly as possible
//                if (isCancelled()) {
//                    break;
//                }
                Log.i(TAG, "processing");
                sleep(50); // simulate long task
            }
            time = System.currentTimeMillis() - time;
            return time;
        }

        @Override
        protected void onCancelled() {
            Log.i(TAG, "cancel");
            AsynNondeterministicActivity activity = mActivityRef.get();
            if (activity != null) {
                if (mProgressDialog != null) {
                    mProgressDialog.dismiss();
                }
                activity.updateStatus("Cancelled");
            }
        }

        @Override
        protected void onPostExecute(Long result) {
            // THIS METHOD RUNS ON UI THREAD
            // --> UPDATE YOUR UI HERE
            Log.i(TAG, "done");
            AsynNondeterministicActivity activity = mActivityRef.get();
            if (activity == null) {
                Log.i(TAG, "skipped --- no acitivity");
                return;
            }

            activity.updateStatus("Done in " + Utils.toDebugString(result));
            if (mProgressDialog != null) {
                mProgressDialog.dismiss();
            }
        }

        // progress dialog's cancel callback
        public void onCancel(DialogInterface dialog) {
            cancel(true);
        }

        public void attach(AsynNondeterministicActivity activity) {
            mActivityRef = new WeakReference<AsynNondeterministicActivity>(activity);
        }

        public void hideProgressDialog() {
            if (mProgressDialog != null) {
                mProgressDialog.dismiss();
            }
        }

        public void resumeProgressDialogIfNeeded() {
            AsynNondeterministicActivity activity = mActivityRef.get();
            if (getStatus() != Status.FINISHED && activity != null) {
                mProgressDialog = new ProgressDialog(activity);
                mProgressDialog.setTitle("Please wait");
                mProgressDialog.setMessage("Processing...");

                mProgressDialog.setCancelable(true);
                mProgressDialog.setOnCancelListener(this);
                mProgressDialog.show();
            }
        }

        private void sleep(long time) {
            try {
                Thread.sleep(time);
            } catch (InterruptedException e) {
            }
        }
    }
}
